package com.geor.gcv.ict;

import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.imageio.ImageIO;

import org.nutz.lang.Files;
import org.nutz.log.Loggers;
import org.opencv.core.Mat;
import org.opencv.core.Size;
import org.opencv.highgui.Highgui;
import org.slf4j.Logger;

import com.geor.gcv.core.mat.Mats;
import com.geor.gcv.core.mat.SurroundArea;
import com.geor.gcv.core.model.Area;
import com.geor.gcv.core.util.DataTool;

/**
 * 碎片生成
 * 
 * @author geor.lusongnan
 *
 */
public class ShardGenerator {
	private static ShardGenerator shardGenerator = new ShardGenerator();
	static Logger log = Loggers.get();

	private ShardGenerator() {

	}

	public static ShardGenerator me() {
		return shardGenerator;
	}

	/**
	 * 生成碎片图片
	 * 
	 * @param configpath
	 *            需要生成的字符
	 * @param targetPath
	 *            目标路径
	 * @param fontType
	 *            字体类型
	 * @param width
	 *            字体宽
	 * @param height
	 *            字体高
	 * @param flag
	 *            结果是否为二值化
	 */
	public void generator(String configpath, String targetPath, String fontType, int width, int height, boolean flag) {
		String base = Files.read(new File(configpath));
		String regs[] = base.split(",");
		List<String> words = new ArrayList<String>();
		int index = 0;
		StringBuffer buffer = new StringBuffer();
		for (String string : regs) {
			if (index++ % 20 == 0) {
				log.info(buffer.toString());
				buffer = new StringBuffer();
			}
			String word = DataTool.convertUTF8ToString(string.trim());
			buffer.append(word + ",");
			words.add(word);
		}
		log.info("There are " + words.size() + " character.");
		try {
			execute(words, targetPath, fontType, width, height, flag);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void execute(List<String> lists, String outpath, String fontType, int width, int height, boolean flag)
			throws IOException {
		Map<String, Mat> maps = new LinkedHashMap<String, Mat>(lists.size());
		StringBuffer s = new StringBuffer();
		int sum = 1000;
		int wordWidth = 50;
		int wordHeight = 50;
		for (int i = 0; i < lists.size(); i++) {
			s.append(lists.get(i));
			if (i != 0 && i % sum == 0 || i == lists.size() - 1) {
				String imgPath = System.getProperty("user.dir") + "/word" + i + ".jpg";
				printImgByStr(imgPath, s.toString(), wordWidth, wordHeight, fontType);
				// 使用opencv读取图片
				Mat mat = Highgui.imread(imgPath, Highgui.CV_LOAD_IMAGE_GRAYSCALE);
				// 字符宽度都是固定
				// 首先得到的碎片图片必须与字符串长度一致
				Area area = new Area(0, 0, wordWidth, wordHeight);
				for (int n = 0; n < s.length(); n++) {
					area.setX(n * wordWidth);
					area.setWidth(wordWidth);
					// 截图
					Mat shard = Mats.screenShoot(mat, area);

					maps.put(String.valueOf(s.charAt(n)), shard);
				}

				mat.release();

				s = new StringBuffer();
			}
		}
		// 生成文件，文字(数字)对应单字符碎片图片
		for (String code : maps.keySet()) {
			Mat shard = maps.get(code);
			int key = DataTool.strTOnumber(code);
			File dir = new File(outpath + "/" + String.valueOf(key));
			if (!dir.exists()) {
				dir.mkdirs();
			}
			Mat bin = Mats.bin(shard, 21, 25);
			Area area = SurroundArea.me().excute(bin);
			shard = Mats.resize(Mats.screenShoot(shard, area), new Size(width, height));
			// 输出
			if (flag) {
				Highgui.imwrite(dir.getAbsolutePath() + "/1.png", Mats.bin(shard, 21, 25));
			} else {
				Highgui.imwrite(dir.getAbsolutePath() + "/1.png", shard);
			}
			dir.renameTo(new File(outpath, code));
		}
	}

	/**
	 * 
	 * @param out
	 *            输出文件
	 * @param content
	 *            内容
	 * @param wordWidth
	 *            字体宽度
	 * @param wordHeight
	 *            字体高度
	 * @param fontName
	 *            字体名称
	 * @throws IOException
	 */
	private void printImgByStr(String out, String content, int wordWidth, int wordHeight, String fontName)
			throws IOException {
		// 输出文件
		File file = new File(out);
		// 确定输出图片的像素
		int width = wordWidth * content.length();
		int height = wordHeight;

		BufferedImage bi = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
		Graphics2D g2 = (Graphics2D) bi.getGraphics();
		g2.setBackground(Color.WHITE);
		g2.clearRect(0, 0, width, height);
		g2.setPaint(Color.BLACK);

		g2.setFont(new Font(fontName, Font.BOLD, height - (int) (height * 0.2)));

		for (int i = 0; i < content.length(); i++) {
			g2.drawString(String.valueOf(content.charAt(i)), i * wordWidth, height - (int) (height * 0.2));
		}

		ImageIO.write(bi, "jpg", file);
	}

}
